﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Timers;

namespace PageAdmin.Utils
{
    /// <summary>
    /// 基于http请求的口令，token工厂类，用于口令的申请，验证，注意每个客户端只能同时保存一个口令
    /// </summary>
    public class HttpTokenHelper
    {
        private string _SessionId;
        private static Dictionary<string, HttpTokenDescriptor> _TokenDictionary;
        private  int _TimeOutMinutes = 5;
        static HttpTokenHelper()
        {
            _TokenDictionary = new Dictionary<string, HttpTokenDescriptor>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sessionId">客户端唯一id，如果是app,小程序等非浏览器应用，请把sessionId保存在本地</param>
        /// <param name="timeOutMinutes">超时分钟数,超时候将会被清除</param>
        public HttpTokenHelper(string sessionId, int timeOutMinutes = 5)
        {
            _SessionId = sessionId;
            if (timeOutMinutes > 0)
            {
                _TimeOutMinutes = timeOutMinutes;
            }
        }

        /// <summary>
        /// 创建并获取token,每个客户端只能保存一个token
        /// </summary>
        private string Create(string token = null)
        {
            if (string.IsNullOrEmpty(_SessionId))
            {
                return null;
            }
            Remove();//获取之前先删除旧的口令，避免冗余产生
            if (string.IsNullOrEmpty(token))
            {
                token = StringHelper.NewGuid();
            }
            HttpTokenDescriptor tokenDescriptor = new HttpTokenDescriptor();
            tokenDescriptor.Token = token;
            tokenDescriptor.ExpiredDate = DateTime.Now.AddMinutes(_TimeOutMinutes);
            _TokenDictionary.Add(_SessionId, tokenDescriptor);
            return token;
        }

        /// <summary>
        /// 获取当前客户端的token
        /// </summary>
        /// <returns></returns>
        public string Get()
        {
            string token = null;
            if (string.IsNullOrEmpty(_SessionId))
            {
                return token;
            }
            if (_TokenDictionary.ContainsKey(_SessionId))
            {
                try
                {
                    token = _TokenDictionary[_SessionId]?.Token;//放try中避免多线程冲突问题
                }
                catch
                {
                    token = Create();
                }
            }
            else
            {
                token = Create();
            }
            return token; ;
        }

        /// <summary>
        /// 验证token
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public TipsInfo Validate(string token)
        {
            TipsInfo tipsInfo = new TipsInfo();
            if (string.IsNullOrEmpty(_SessionId))
            {
                tipsInfo.State = 0;
                tipsInfo.Msg = "无效的sessionId";
            }
            else if (!_TokenDictionary.ContainsKey(_SessionId))
            {
                tipsInfo.State = 0;
                tipsInfo.Msg = "token口令过期失效";
            }
            else
            {
                try
                {
                    HttpTokenDescriptor tokenDescriptor = _TokenDictionary[_SessionId];
                    if (string.IsNullOrEmpty(token) || !tokenDescriptor.Token.Equals(token, StringComparison.OrdinalIgnoreCase))
                    {
                        tipsInfo.State = 0;
                        tipsInfo.Msg = "token口令验证失败";
                    }
                }
                catch
                {
                    tipsInfo.State = 0;
                    tipsInfo.Msg = "token口令过期失效";
                }
            }
            return tipsInfo;
        }

        /// <summary>
        /// 移除对应客户端的所有token
        /// </summary>
        /// <param name="clientId"></param>
        public void Remove()
        {
            if (!string.IsNullOrEmpty(_SessionId) && _TokenDictionary.ContainsKey(_SessionId))
            {
                _TokenDictionary.Remove(_SessionId);
            }
        }

        /// <summary>
        /// 定时清理过期的token
        /// </summary>
        [AutoTask]
        private static string ClearExpired()
        {
            string result = null;
            int i = 0;
            foreach (string key in _TokenDictionary.Keys.ToList())
            {
                try
                {
                    HttpTokenDescriptor item = _TokenDictionary[key];
                    DateTime expiredTime = item.ExpiredDate;
                    TimeSpan ts = DateTime.Now - expiredTime;
                    if (ts.TotalMinutes>0)
                    {
                        _TokenDictionary.Remove(key);
                        i++;
                    }
                }
                catch (Exception ex)
                {
                    result=$"httpToken定时清理失败：{ex.Message}";
                    return result;
                }
            }
            if (i > 0)
            {
                result = $"httpToken定时清理任务,成功数：{i}";
            }
            return result;
        }
    }

    /// <summary>
    /// Token描述类
    /// </summary>
    [Serializable]
    internal class HttpTokenDescriptor
    {
        /// <summary>
        /// token
        /// </summary>
        public string Token { get; set; }

        /// <summary>
        /// 过期时间
        /// </summary>
        public DateTime ExpiredDate { get; set; }
    }
}
